﻿/*
 * @Author: song
 * @Description:事件派发
 * @Date: 2024年04月14日 星期日 17:04:58
 * @Modify:
 */

using System;
using System.Collections.Generic;
using SCore.Util;

namespace SCore.Util
{
    public class EventManager
    {
        private Dictionary<int, Delegate> _eventTable = new Dictionary<int, Delegate>();

        ~EventManager()
        {
            _eventTable.Clear();
        }

        private void OnListenerAdding(int gameEventType, Delegate Action)
        {
            if (!_eventTable.ContainsKey(gameEventType))
            {
                _eventTable.Add(gameEventType, null);
            }

            var @delegate = _eventTable[gameEventType];
            if (@delegate != null && @delegate.GetType() != Action.GetType())
            {
                $"尝试为事件{gameEventType}添加不同类型的委托,当前事件对应的委托是{@delegate.GetType()},要添加的委托类型是{Action.GetType()}".Error();
            }
        }

        private void OnListenerRemoving(int gameEventType, Delegate Action)
        {
            // 判断对应EventSystemType是否存在，如果不存在或者类型错误则无法移除
            if (_eventTable.ContainsKey(gameEventType))
            {
                var @delegate = _eventTable[gameEventType];
                if (@delegate == null)
                {
                    $"移除监听错误：事件{gameEventType}没有对应的委托".Warn();
                }
                else if (@delegate.GetType() != Action.GetType())
                {
                    $"尝试为事件移除{gameEventType}不同类型的委托，当前委托类型为{@delegate.GetType()}，要移除的委托类型为{Action.GetType()}".Warn();
                }
            }
            else
            {
                $"移除监听错误，没有事件码{gameEventType}".Warn();
            }
        }

        private void OnListenerRemoved(int gameEventType)
        {
            if (_eventTable[gameEventType] == null)
            {
                _eventTable.Remove(gameEventType);
            }
        }

        public void AddListener(int gameEventType, Action Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action)_eventTable[gameEventType] + Action;
        }

        public void AddListener<T>(int gameEventType, Action<T> Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T>)_eventTable[gameEventType] + Action;
        }

        public void AddListener<T, X>(int gameEventType, Action<T, X> Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X>)_eventTable[gameEventType] + Action;
        }

        public void AddListener<T, X, Y>(int gameEventType, Action<T, X, Y> Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y>)_eventTable[gameEventType] + Action;
        }

        public void AddListener<T, X, Y, Z>(int gameEventType, Action<T, X, Y, Z> Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y, Z>)_eventTable[gameEventType] + Action;
        }

        public void AddListener<T, X, Y, Z, W>(int gameEventType, Action<T, X, Y, Z, W> Action)
        {
            OnListenerAdding(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y, Z, W>)_eventTable[gameEventType] + Action;
        }

        // 移除监听器的方法
        public void RemoveListener(int gameEventType, Action Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void RemoveListener<T>(int gameEventType, Action<T> Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T>)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void RemoveListener<T, X>(int gameEventType, Action<T, X> Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X>)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void RemoveListener<T, X, Y>(int gameEventType, Action<T, X, Y> Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y>)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void RemoveListener<T, X, Y, Z>(int gameEventType, Action<T, X, Y, Z> Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y, Z>)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void RemoveListener<T, X, Y, Z, W>(int gameEventType, Action<T, X, Y, Z, W> Action)
        {
            OnListenerRemoving(gameEventType, Action);
            _eventTable[gameEventType] = (Action<T, X, Y, Z, W>)_eventTable[gameEventType] - Action;
            OnListenerRemoved(gameEventType);
        }

        public void BroadCast(int gameEventType)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action;
                if (Action != null)
                {
                    Action();
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }

        public void BroadCast<T>(int gameEventType, T arg)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action<T>;
                if (Action != null)
                {
                    Action(arg);
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }

        public void BroadCast<T, X>(int gameEventType, T args1, X args2)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action<T, X>;
                if (Action != null)
                {
                    Action(args1, args2);
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }

        public void BroadCast<T, X, Y>(int gameEventType, T args1, X args2, Y args3)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action<T, X, Y>;
                if (Action != null)
                {
                    Action(args1, args2, args3);
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }

        public void BroadCast<T, X, Y, Z>(int gameEventType, T args1, X args2, Y args3, Z args4)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action<T, X, Y, Z>;
                if (Action != null)
                {
                    Action(args1, args2, args3, args4);
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }

        public void BroadCast<T, X, Y, Z, W>(int gameEventType, T args1, X args2, Y args3, Z args4,
            W args5)
        {
            Delegate @delegate;
            if (_eventTable.TryGetValue(gameEventType, out @delegate))
            {
                var Action = @delegate as Action<T, X, Y, Z, W>;
                if (Action != null)
                {
                    Action(args1, args2, args3, args4, args5);
                }
                else
                {
                    $"广播事件错误，事件{gameEventType}对应的委托有不同的类型".Warn();
                }
            }
        }
    }
}